package com.ltmonitor.web.controller;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import javax.swing.text.FieldView;

import com.ltmonitor.service.*;
import com.ltmonitor.video.entity.VideoServerConfig;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.ltmonitor.entity.AlarmConfig;
import com.ltmonitor.entity.AlarmRecord;
import com.ltmonitor.entity.BasicData;
import com.ltmonitor.entity.Department;
import com.ltmonitor.entity.GPSRealData;
import com.ltmonitor.util.Constants;
import com.ltmonitor.util.DateUtil;
import com.ltmonitor.util.StringUtil;
import com.ltmonitor.vo.PaginateResult;
import com.ltmonitor.web.util.OnlineUser;

/**
 * 针对分页查询的通用Action
 */
@Controller
public class PaginateAction extends GenericAction {

	@Autowired
	private IAlarmConfigService alarmConfigService;

	@Autowired
	private IReportConfigService reportConfigService;

	@Autowired
	private IRealDataService realDataService;


	public String view() {
		return "input";
	}

	/**
	 * 分页查询
	 */
	@RequestMapping("/paginate.action")
	@ResponseBody
	public PaginateResult execute(String queryId,
			@RequestParam(value = "page", defaultValue = "1") int page,
			@RequestParam(value = "rows", defaultValue = "10") int rows,
			@RequestParam(value = "depId", defaultValue = "0") int depId,
			String fileName) {
		OnlineUser user = super.getOnlineUser();
		if (queryId == null || queryId.isEmpty() || user == null)
			return new PaginateResult();
		/**
		 * 如果报表文件名不为空，说明是报表查询，记录到系统日志中
		 */
		if (StringUtil.isNullOrEmpty(fileName) == false && page <= 1) {
			this.LogOperation("查询 " + fileName);
		}

		try {
			Map parameters = this.getParams();
			Map paraMap = new HashMap(parameters);
			paraMap.put("userId", user.getEntityId());
			paraMap.put("superAdmin", user.isSuperAdmin());// 是否是超级用户

			// depId是用户选择的查询部门，按部门查询条件，部门及下级部门下的数据
			if (depId > 0) {
				List<Long> depIdList = super.getDepartmentService()
						.getDepIdList(depId);
				paraMap.put("depIdList", depIdList);
				paraMap.remove("depId");
			} else if (this.getOnlineUser().getCompanyId() > 0
					&& this.getOnlineUser().isSuperAdmin() == false) {
				//用户所属公司及级联下级部门的公司，作为限定查询条件
				List<Long> depIdList = super.getDepartmentService()
						.getDepIdList(this.getOnlineUser().getCompanyId());
				paraMap.put("companyIdList", depIdList);
				paraMap.remove("depId");

			} else
				paraMap.remove("depId");

			// 如果当前页为零，则默认为1
			page = page == 0 ? 1 : page;
			if ("user.selectUsers".equals(queryId)
					&& user.isSuperAdmin() == false) {
				// 区域限制，只能同区域或区域下面的子区域的用户
				long regionId = this.getOnlineUser().getCompanyId();
				if (regionId > 0
						&& this.getOnlineUser().isSuperAdmin() == false) {
					List<Long> regionIdList = super.getDepartmentService()
							.getDepIdList(regionId);
					paraMap.put("companyIdList", regionIdList);
				}
			}

			// Map params = new HashMap();
			PaginateResult result = queryService.queryByPagination(queryId,
					paraMap, page, rows);

			for (Object rowData : result.getRows()) {
				try {
					// 对返回的每行数据，进行格式化转换
					convert(queryId, (Map) rowData);
				} catch (Exception ex) {
					log.error(ex.getMessage(), ex);
				}
			}

			return result;
		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
		}

		return new PaginateResult();
	}

	/**
	 * 导出时不带分页，要查出所有结果
	 * 
	 * @return
	 */
	@RequestMapping("/export.action")
	public void export(String queryId, String fileName,
			@RequestParam(value = "depId", defaultValue = "0") int depId,
			HttpServletResponse response) {
		/**
		 * 如果报表文件名不为空，说明是报表查询，记录到系统日志中
		 */
		if (StringUtil.isNullOrEmpty(fileName) == false) {
			this.LogOperation("报表导出 " + fileName);
		}
		OutputStream outStream = null;
		try {
			Map params = this.getParams();
			params.put("userId", this.getOnlineUser().getEntityId());
			// params.put("depIdList", super.getAuthorizedDepIdList());

			if (depId > 0) {
				List<Long> depIdList = super.getDepartmentService()
						.getDepIdList(depId);
				params.put("depIdList", depIdList);
				params.remove("depId");
			} else if (this.getOnlineUser().getCompanyId() > 0
					&& this.getOnlineUser().isSuperAdmin() == false) {
				//用户所属公司及级联下级部门的公司，作为限定查询条件
				List<Long> depIdList = super.getDepartmentService()
						.getDepIdList(this.getOnlineUser().getCompanyId());
				params.put("companyIdList", depIdList);
				params.remove("depId");

			} else
				params.remove("depId");

			
			List<Map<String, Object>> list = this.queryService.query(queryId,
					params);
			for (Object rowData : list) {
				try {
					// 对返回的每行数据，进行格式化转换
					convert(queryId, (Map) rowData);
				} catch (Exception ex) {
					log.error(ex.getMessage(), ex);
				}
			}
			if (fileName == null)
				fileName = queryId;
			String reportName = fileName;
			fileName += DateUtil.toStringByFormat(new Date(), "yyMMddHHmmss")
					+ ".xls";

			String agent = (String) getRequest().getHeader("USER-AGENT");
			if (agent != null && agent.toLowerCase().indexOf("firefox") >= 0) {
				fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");//解决firefox浏览器下载文件名乱码问题
			} else {
				fileName = java.net.URLEncoder.encode(fileName, "UTF-8");
			}

			// 将工作簿写入最上面定义的InputStream流——名称为excelStream，这个名字对应struts.xml中配置的inputName参数
			HSSFWorkbook workbook = getWorkbook(queryId, list, queryId, 0,
					params, reportName);
			if (workbook != null) {
				response.setContentType("application/vnd.ms-excel;"); 
				response.setHeader("Content-disposition",
						"attachment;filename=" + fileName);
				outStream = response.getOutputStream();
				workbook.write(outStream);
			}

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			if (outStream != null) {
				try {
					outStream.flush();
					outStream.close();
				} catch (IOException e) {
					log.error(e.getMessage(), e);
				}
			}
		}
	}

	private HSSFCell createCell(HSSFRow row, int col, String value) {
		HSSFCell cell = row.createCell(col++); // 创建第i列
		cell.setCellType(HSSFCell.CELL_TYPE_STRING);
		// cell.setEncoding(HSSFCell.ENCODING_UTF_16);
		cell.setCellValue(value);
		return cell;
	}

	private HSSFWorkbook getWorkbook(String queryId, List list,
			String sheetNames, int isSum, Map params, String reportName)
			throws Exception {
		List<String> queryConditionNames = reportConfigService
				.getQueryConditionMap().get(queryId);

		List<String> columns = reportConfigService.getColumnMap().get(queryId);
		String[] columnNames = new String[columns.size()];
		String[] headers = new String[columns.size()];
		for (int m = 0; m < columns.size(); m++) {
			String[] strName = columns.get(m).split(",");
			columnNames[m] = strName[0];
			headers[m] = strName[1];
		}
		HSSFWorkbook workbook = new HSSFWorkbook();// 创建Excel文件

		HSSFCellStyle style = workbook.createCellStyle(); // 样式对象
		style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 指定单元格垂直居中对齐
		// //////////////////

		HSSFSheet sheet = workbook.createSheet();// 创建sheet
		workbook.setSheetName(0, reportName);// HSSFCell.ENCODING_UTF_16);为指定第K个sheet命名，并设定字符集类型
		int rowNo = 0;

		HSSFRow row = sheet.createRow(rowNo++); // 创建第1行，也就是输出表头
		createCell(row, 1, reportName);
		// int columnNum = columns.size();
		if (queryConditionNames != null) {
			row = sheet.createRow(rowNo++); // 创建第1行，也就是输出表头
			int col = 0;
			createCell(row, col, "查询条件:");

			HSSFCellStyle ss = workbook.createCellStyle();
			ss.setFillForegroundColor(HSSFColor.RED.index);
			HSSFFont font = workbook.createFont();
			font.setFontName(HSSFFont.FONT_ARIAL);// 字体
			// font.setFontHeightInPoints((short) 20);//字号
			font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);// 加粗
			font.setColor(HSSFColor.BLUE.index);// 颜色
			ss.setFont(font);

			for (int m = 0; m < queryConditionNames.size(); m++) {
				String[] strName = queryConditionNames.get(m).split(",");
				String param = strName[0];
				String paramName = strName[1] + "：";
				String paramValue = "" + params.get(param);
				if (param.equals("depId") && params.get(param) != null) {
					int depId = Integer.parseInt(paramValue);
					if (depId > 0) {
						Department dep = this.getDepartmentService()
								.fetchDepartment(depId);
						if (dep != null)
							paramValue = dep.getName();
					} else
						paramValue = "无";
				}
				if (params.get(param) == null)
					paramValue = "无";
				// if (StringUtil.isNullOrEmpty(paramValue) == false ) {
				if (paramValue.indexOf("请选择") >= 0)
					paramValue = "全部";
				// paramValue += params.get(param);
				if (col % 8 == 0) {
					row = sheet.createRow(rowNo++); // 创建第1行，也就是输出表头
					col = 0;
				}
				createCell(row, col++, paramName);
				HSSFCell cell = createCell(row, col++, paramValue);
				// ss.setFont(font)
				cell.setCellStyle(ss);
				// }
			}
		}

		row = sheet.createRow(rowNo++); // 创建数据表格标题第1行，也就是输出表头
		// cell = row.createCell((short) 0);
		// cell.setCellType(HSSFCell.CELL_TYPE_STRING);
		// cell.setEncoding(HSSFCell.ENCODING_UTF_16);
		for (short i = 0; i < headers.length; i++) {
			createCell(row, i, headers[i]);
		}

		List colunData = null;
		// 下面是输出各行的数据(留出最后一行，如果是合计信息单独输出，如果非合计信息按照原本样式输出)

		HSSFPatriarch patri = sheet.createDrawingPatriarch();
		for (int i = 0; i < list.size(); i++) {
			Map rowData = (Map) list.get(i);
			row = sheet.createRow(rowNo++);// 创建第i行
			for (short j = 0; j < columnNames.length; j++) {
				// cell = row.createCell(j); // 创建第j列
				// cell.setCellType(HSSFCell.CELL_TYPE_STRING);
				// cell.setEncoding(HSSFCell.ENCODING_UTF_16);
				String colName = columnNames[j];
				Object fieldValue = rowData.get(colName);
				String value = "" + (fieldValue == null ? "" : fieldValue);// 通过列名找到字段值
				// cell.setCellValue(value);
				if ("selectVehiclePictures".equals(queryId)
						&& "fileName".equals(colName)) {
					ByteArrayOutputStream outStream = new ByteArrayOutputStream();
					String fileName = request.getRealPath("/")
							+ "vehiclePicture/" + value;
					File f = new File(fileName);
					boolean res = f.isFile();
					if (res == false)
						continue;
					BufferedImage bufferImg = null;
					try {
						bufferImg = ImageIO.read(f);
						if (bufferImg == null)
							continue;
						ImageIO.write(bufferImg, "PNG", outStream);
						// 利用HSSFPatriarch将图片写入EXCEL
						HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0,
								0, (short) j, row.getRowNum(), (short) (j + 1),
								row.getRowNum() + 1);
						patri.createPicture(anchor, workbook.addPicture(
								outStream.toByteArray(),
								HSSFWorkbook.PICTURE_TYPE_PNG));
						// 列宽
						sheet.setColumnWidth((short) j, 4280);
						// 行高
						row.setHeight((short) 1560);
					} catch (Exception ex) {

					} finally {
						if (outStream != null)
							outStream.close();
						if (bufferImg != null)
							bufferImg.flush();
					}
				} else {
					createCell(row, j, value);
				}

			}
		}

		return workbook;
	}

	protected void convert(String queryId, Map rowData) {
		Map<String, String> fieldConfig = reportConfigService
				.getQueryConfigMap().get(queryId);
		if (fieldConfig != null) {
			Set<String> fields = fieldConfig.keySet();
			for (String field : fields) {
				String parentCode = fieldConfig.get(field);
				String fieldValue = "" + rowData.get(field);

				if (field.equals("plateNo") && parentCode.equals("depName")) {
					// 根据车辆转换成部门
					String depName = "";
					Department dep = vehicleDataService
							.getDepartmentByPlateNo(fieldValue);
					if (dep != null)
						depName = dep.getName();
					rowData.put("depName", depName);
				} else if (parentCode.equals("timeSpan")) {
					if(StringUtil.isNullOrEmpty(fieldValue))
						continue;;
					Double timeSpan = Double.parseDouble(fieldValue);
					if (timeSpan >= 0) {
						rowData.put(field, Constants.getIntervalDescr(timeSpan));
					} else {
						String status = "" + rowData.get("status");
						if (status.equals("New")) {
							Date startTime = (Date) rowData.get("startTime");
							timeSpan = 0.1 * DateUtil.getSeconds(startTime,
									new Date()) / 6;
						}
						rowData.put(field, Constants.getIntervalDescr(timeSpan));
					}
				}
				else if (parentCode.equals("FileSize")) {
					if(StringUtil.isNullOrEmpty(fieldValue))
						continue;;
					fieldValue = Constants.formatFileSize(fieldValue);
					rowData.put(field, fieldValue);

				}
				else if (parentCode.equals("KBFileSize")) {
					if(StringUtil.isNullOrEmpty(fieldValue))
						continue;;
					int f = Integer.parseInt(fieldValue) / 1024;
					fieldValue = Constants.formatFileSize(""+f);
					rowData.put(field, fieldValue);

				}
				else if (parentCode.equals("GpsStatus")) {
					String status = getStatusDescr(fieldValue);
					rowData.put(field, status);
				} else if (parentCode.equals("onlineStatus")) {
					String simNo = fieldValue;
					String online = "离线";
					GPSRealData rd = realDataService.get(simNo);
					if (rd != null && rd.getOnline()) {
						// 将实时数据更新到map
						online = "在线";
						rowData.put("sendTime", rd.getOnlineDate());
						rowData.put("onlineDate", rd.getOnlineDate());
					}

					rowData.put("online", online);

					Date sendTime = (Date) rowData.get("onlineDate");
					if (sendTime != null) {
						double seconds = DateUtil.getSeconds(sendTime,
								new Date()) / 60;
						rowData.put("offlineTimeSpan",
								Constants.getIntervalDescr(seconds));
					}

				} else if (parentCode.equals("AlarmType")
						|| parentCode.equals("alarmType")) {
					String alarmType = fieldValue;
					String alarmSource = "" + rowData.get("alarmSource");
					if (rowData.containsKey("alarmSource") == false
							&& rowData.containsKey("type"))
						alarmSource = "" + rowData.get("type");
					if(StringUtil.isNullOrEmpty(alarmSource) && (AlarmRecord.TYPE_ONLINE.equals(alarmType) || AlarmRecord.TYPE_OFFLINE.equals(alarmType)))
					{
						//上下线默认为平台报警
						alarmSource = AlarmRecord.ALARM_FROM_PLATFORM;
					}
					AlarmConfig ac = this.alarmConfigService.getDefaultAlarmConfig(alarmType, alarmSource);

					if (ac != null) {
						String alarmTypeDescr = ac.getName();
						if (AlarmRecord.TYPE_OVER_SPEED.equals(ac
								.getAlarmType())) {
							if (rowData.get("speed") != null) {
								String speed = "" + rowData.get("speed");
								alarmTypeDescr += ",速度:" + speed + "km/h";
							}
						} else if (AlarmRecord.TYPE_TIRED.equals(ac
								.getAlarmType())) {
							if (rowData.get("descr") != null) {
								alarmTypeDescr += "," + rowData.get("descr");
							}
						}
						rowData.put(field, alarmTypeDescr);
					}
				}
				else if (field.equals("filePath")) {
					String fileName = this.searchFileName(fieldValue);
					rowData.put("fileName", fileName);
				}
				else if (parentCode.equals("DirectionDescr")) {
					int direction = Integer.parseInt(fieldValue);
					String strDirection = this.getDirectionDescr(direction);
					rowData.put("directionDescr", strDirection);
				} else if (parentCode.equals("AlarmStateDescr")) {
					int alarmState = Integer.parseInt(fieldValue);
					String strAlarmState = this.getAlarmDescr(alarmState);
					rowData.put("alarmStateDescr", strAlarmState);
				}
				else if (parentCode.equals("VideoAlarmStateDescr")) {
					long alarmState = Long.parseLong(fieldValue);
					String strAlarmState = this.getVideoAlarmDescr(alarmState);
					rowData.put("alarmStateDescr", strAlarmState);
				}
				else if (parentCode.equals("808CmdType")) {
					try {
						Integer cmdType = (Integer) rowData.get(field);
						String strCmd = Integer.toHexString(cmdType);
						if (strCmd.length() < 4)
							strCmd = "0" + strCmd;
						strCmd = "0x" + strCmd;
						String descr = JT808Constants.GetDescr(strCmd);
						rowData.put(field, descr);
					} catch (Exception e) {
						log.error(e.getMessage(), e);
					}
				} else {
					this.convert(rowData, field, parentCode);
				}
			}
		}
	}


	public  String searchFileName(String filePath) {// 递归查找包含关键字的文件
		String strDir = getVideoServerConfig().getFtpPath() + "\\" + filePath;
		File d = new File(strDir);
		if (d.isDirectory()) {
			File[] fs = d.listFiles();
			for (int i = 0; i < fs.length; i++) {
				File f = fs[i];
				String fileName = f.getName();
				if (fileName.endsWith(".264") || fileName.endsWith(".avi") || fileName.endsWith(".mp4")) {
					return f.getName();

				}
			}
		}else
		{
			return d.getName();
		}
		return null;

	}


	protected String getStatusDescr(String strStatus) {

		int status = Integer.parseInt(strStatus);
		strStatus = Integer.toBinaryString(status);
		strStatus = StringUtil.leftPad(strStatus, 32, '0');
		// strStatus = getStatusDescr(strStatus);

		StringBuilder sb = new StringBuilder();

		if (StringUtil.isNullOrEmpty(strStatus) == false) {
			char[] ch = strStatus.toCharArray();
			if (ch.length == 32) {
				int m = 31;
				int c = ch[m - 0] - 48;
				sb.append(c == 1 ? "ACC开" : "ACC关").append(",");
				c = ch[m - 1] - 48;
				sb.append(c == 1 ? "定位" : "未定位").append(",");
				c = ch[m - 4] - 48;
				sb.append(c == 1 ? "停运" : "运营").append(",");
				c = ch[m - 10] - 48;
				sb.append(c == 1 ? "油路断开" : "油路正常").append(",");
				c = ch[m - 11] - 48;
				sb.append(c == 1 ? "电路断开" : "电路正常").append(",");
				c = ch[m - 12] - 48;
				sb.append(c == 1 ? "车门加锁" : "车门解锁").append(",");
			}
		}

		return sb.toString();
	}

	protected String getDirectionDescr(int direction) {
		Map directionMap = new HashMap();
		String descr = "";
		if (direction == 0) {
			descr = "正东";
		} else if (direction == 90) {
			descr = "正北";
		} else if (direction == 180) {
			descr = "正西";
		} else if (direction == 270) {
			descr = "正南";
		} else if (direction == 45) {
			descr = "东北";
		} else if (direction == 135) {
			descr = "西北";
		} else if (direction == 225) {
			descr = "西南";
		} else if (direction == 315) {
			descr = "东南";
		} else if (direction < 90) {
			descr = "东偏北" + direction + "度";
		} else if (direction > 90 && direction < 180) {
			descr = "西偏北" + (180 - direction) + "度";
		} else if (direction > 180 && direction < 270) {
			descr = "西偏南" + (direction - 180) + "度";
		} else if (direction > 270 && direction < 360) {
			descr = "东偏南" + (360 - direction) + "度";
		}
		return descr;
	}

	/**
	 * 报警描述
	 * 
	 * @param alarmState
	 * @return
	 */
	protected String getAlarmDescr(int alarmState) {
		if(alarmState == 0)
			return "";
		StringBuilder sb = new StringBuilder();
		String alarm = Integer.toBinaryString(alarmState);
		alarm = StringUtil.leftPad(alarm, 32, '0');
		if (StringUtil.isNullOrEmpty(alarm) == false) {
			char[] ch = alarm.toCharArray();
			for (int m = 0; m < ch.length; m++) {
				int tag = Integer.parseInt("" + ch[m]);
				if (tag == 1) {
					int alarmId = 31 - m; // 倒序，转换为部标的报警序号
					BasicData bd = basicDataService.getBasicDataByCode(""
							+ alarmId, "AlarmType");
					if (bd != null) {
						sb.append(bd.getName()).append(",");
					}
				}
			}
		}

		return sb.toString();
	}

	/**
	 * 报警描述
	 *
	 * @param alarmState
	 * @return
	 */
	protected String getVideoAlarmDescr(long alarmState) {
		if(alarmState == 0)
			return "";
		StringBuilder sb = new StringBuilder();
		String alarm = Long.toBinaryString(alarmState);
		alarm = StringUtil.leftPad(alarm, 64, '0');
		if (StringUtil.isNullOrEmpty(alarm) == false) {
			char[] ch = alarm.toCharArray();
			for (int m = 0; m < ch.length; m++) {
				int tag = Integer.parseInt("" + ch[m]);
				if (tag == 1) {
					int alarmId = 63 - m; // 倒序，转换为部标的报警序号
					String alarmType = alarmId > 31 ? AlarmRecord.ALARM_FROM_VIDEO : AlarmRecord.ALARM_FROM_TERM;
					AlarmConfig bd = alarmConfigService.getDefaultAlarmConfig(""
							+ alarmId, alarmType);
					if (bd != null) {
						if(sb.length() > 0)
							sb.append(",");
						sb.append(bd.getName());
					}
				}
			}
		}

		return sb.toString();
	}

}
